package com.kaguya.state;

import java.util.Random;

/**
 * 行为型，状态模式，把状态作为类，通过改变类来改变具体的状态
 * 减少if else，用类来表示状态
 * 将大而复杂的问题分解，分而治之
 * 本例不是很好，主要思路是将状态用类来表示，用另一个管理器来集中管理分配不同的状态
 */
public class Test {
    public static void main(String[] args) throws InterruptedException {
        // 白天和夜晚的行为不一样
        ContextImpl context = new ContextImpl();
        // 随机一个时间
        for (int i = 0; i< 5; i++) {
            Random randomTime = new Random();
            int time = randomTime.nextInt(23);
            System.out.println("当前时间: " + time + "点");

            context.setClock(time);
            State state = ContextImpl.state;

            state.doUse(context);
            state.doAlarm(context);
            state.doPhone(context);
            System.out.println("-------------");
            Thread.sleep(2000);
        }
    }
}

/**
 * 状态接口
 */
interface State {
    void doClock(Context context, int hour); // 设置时间
    void doUse(Context context); // 使用金库
    void doAlarm(Context context); // 按下警铃
    void doPhone(Context context); // 正常通话
}

/**
 * 白天状态类
 */
class DayState implements State{
    // 提供唯一实例给管理器
    private static DayState dayState = new DayState();

    public static DayState getInstance() {return dayState;}

    /**
     * 设置时间（改变状态）
     * @param context
     * @param hour
     */
    @Override
    public void doClock(Context context, int hour) {
        if(hour < 9 || 17 <= hour) {
            context.changeState(NightState.getInstance());
        }
    }

    /**
     * 使用金库
     * @param context
     */
    @Override
    public void doUse(Context context) {
        context.recoding("使用金库，（白天）");
    }

    /**
     * 按下警铃
     * @param context
     */
    @Override
    public void doAlarm(Context context) {
        context.callSecurityCenter("按下警铃，（白天）");
    }

    /**
     * 正常通话
     * @param context
     */
    @Override
    public void doPhone(Context context) {
        context.callSecurityCenter("正常通话，（白天）");
    }

    public String showInfo() {
        return "[白天]";
    }
}

/**
 * 白天状态类
 */
class NightState implements State{
    // 提供唯一实例给管理器
    private static NightState nightState = new NightState();

    public static NightState getInstance() {return nightState;}

    /**
     * 设置时间
     * @param context
     * @param hour
     */
    @Override
    public void doClock(Context context, int hour) {
        if(hour > 9 || 17 > hour) {
            context.changeState(DayState.getInstance());
        }
    }

    /**
     * 使用金库
     * @param context
     */
    @Override
    public void doUse(Context context) {
        context.callSecurityCenter("紧急，晚上使用金库");
    }

    /**
     * 按下警铃
     * @param context
     */
    @Override
    public void doAlarm(Context context) {
        context.callSecurityCenter("按下警铃，（晚上）");
    }

    /**
     * 正常通话
     * @param context
     */
    @Override
    public void doPhone(Context context) {
        context.recoding("晚上的通话录音");
    }

    public String showInfo() {
        return "[晚上]";
    }
}

/**
 * 管理器接口
 */
interface Context {
    void setClock(int hour); // 设置时间
    void changeState(State state); // 改变状态
    void callSecurityCenter(String msg); // 联系警报中心
    void recoding(String msg); // 在报警中心留下记录
}

/**
 * 管理者实现
 */
class ContextImpl implements Context {

    public static State state = DayState.getInstance();

    @Override
    public void setClock(int hour) {
        state.doClock(this,hour);
    }

    @Override
    public void changeState(State state) {
        System.out.println("状态改变了。。");
        ContextImpl.state = state;
    }

    @Override
    public void callSecurityCenter(String msg) {
        System.out.println(msg);
    }

    @Override
    public void recoding(String msg) {
        System.out.println(msg);
    }
}


